package com.beeasy.hzbpm.cron;

import cn.hutool.core.io.FileUtil;
import com.beeasy.hzbpm.entity.BpmTrigger;
import com.beeasy.hzbpm.service.BpmService;
import com.beeasy.hzbpm.service.TriggerService;
import com.github.llyb120.nami.cron.ICron;
import com.github.llyb120.json.Json;
import org.bson.Document;
import org.bson.types.ObjectId;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.function.Consumer;

import static com.beeasy.hzbpm.bean.MongoService.db;
import static com.github.llyb120.json.Json.*;

public class BpmTriggerLoop implements ICron {

    static File lastTriggered = new File(System.getProperty("user.dir"), "last_triggered");
    static {
        lastTriggered.mkdirs();
    }

    @Override
    public void run() throws Exception {
        //上一次的执行时间
        db.getCollection("workflow").aggregate(
            a(
                o(
                    "$match", o(
                        "trigger", o("$exists", true)
                    )
                ),
                o(
                    "$project", o(
                        "trigger", 1
                    )
                )
            ).toBson()
        ).forEach((Consumer<? super Document>) e -> {
            check(e);
        });
    }

    private void check(Document doc){
        ObjectId bpmId = doc.getObjectId("_id");
        List list = ro(doc).get("trigger.list", List.class);//Json.get(doc, "trigger.list");
        if (list == null) {
            return;
        }
        for (int i = 0; i < list.size(); i++) {
            BpmTrigger trigger = Json.cast(list.get(i), BpmTrigger.class);
            if(!trigger.event.equals("EVENT_LOOP")){
                continue;
            }
            //上一次触发的时间
            boolean success = false;
            File file = new File(lastTriggered, bpmId + "_" + i);
            long now = System.currentTimeMillis();
            try{
                long last = Long.parseUnsignedLong(FileUtil.readUtf8String(file));
                if(now - last > calculateMillionSeconds(trigger)){
                    success = true;
                }
            } catch (IOException e){
                success = false;
            } catch (Exception e){
                success = true;
            } finally {
                FileUtil.writeUtf8String(now + "", file);
            }
            if(!success){
                continue;
            }

            db.getCollection("bpmInstance").aggregate(
                a(
                    o("$match", o("bpmId", bpmId, "state", "流转中"))
                ).toBson()
            ).forEach((Consumer<? super Document>) e -> {
                BpmService service = BpmService.ofIns(e);
                TriggerService.trigger(service, "EVENT_LOOP", null);
            });
        }
    }

    private long calculateMillionSeconds(BpmTrigger trigger) throws IOException {
        try{
            int step = Integer.parseUnsignedInt(trigger.loop);
            if(trigger.unit.equals("hour")){
                return step * 3600 * 1000;
            } else if(trigger.unit.equals("second")){
                return step * 1000;
            }
            return Long.MAX_VALUE;
        } catch (Exception e){
            throw new IOException();
        }
    }
}
